<?php
namespace app\common\lib\RoyCloud\Common;

abstract class AbstractModel
{
    public function serialize()
    {
        $ret = $this->objSerialize($this);
        return $ret;
    }

    private function objSerialize($obj)
    {
        $members = [];
        try {
            $ref = new \ReflectionClass($obj);
            $memberList = $ref->getProperties();
            foreach ($memberList as $k => $member) {
                $name = ucfirst($member->getName());
                $member->setAccessible(true);
                $value = $member->getValue($obj);
                if ($value === null) {
                    continue;
                }
                if ($value instanceof AbstractModel) {
                    $members[$name] = $this->objSerialize($value);
                } elseif (is_array($value)) {
                    $members[$name] = $this->arraySerialize($value);
                } else {
                    $members[$name] = $value;
                }
            }
            return $members;
        } catch (\ReflectionException $e) {
            return [];
        }
    }

    private function arraySerialize($list)
    {
        $members = [];
        foreach ($list as $name => $value) {
            if ($value === null) {
                continue;
            }
            if ($value instanceof AbstractModel) {
                $members[$name] = $this->objSerialize($value);
            } elseif (is_array($value)) {
                $members[$name] = $this->arraySerialize($value);
            } else {
                $members[$name] = $value;
            }
        }
        return $members;
    }

    abstract public function deserialize($param);

    /**
     * @param mixed $param 数组或 json 格式字符串
     */
    public function fromParam($param)
    {
        if (is_string($param)) {
            $param = json_decode($param, true);
        }
        $this->deserialize($param);
    }

    public function toString()
    {
        $r = $this->serialize();
        if (empty($r)) {
            return '{}';
        }
        return json_encode($r, JSON_UNESCAPED_UNICODE);
    }

    public function __call($member, $param)
    {
        $act = substr($member, 0, 3);
        $attr = substr($member, 3);
        if ($act === 'get') {
            return $this->$attr;
        } elseif ($act === 'set') {
            $this->$attr = $param[0];
        }
        return true;
    }
}
